package com.github.llyb120.sxmanage;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.stream.Collectors;

import static com.github.llyb120.sxmanage.LogServer.*;
import static com.github.llyb120.sxmanage.Util.HandleScript;
import static com.github.llyb120.sxmanage.Util.RunScript;
import static com.github.llyb120.sxmanage.WebSocketServer.findByName;
import static com.github.llyb120.sxmanage.WebSocketServer.send;

/**
 * @Author: Administrator
 * @Date: 2020/12/12 16:00
 */
@ServerEndpoint("/update/{name}/{file}")
@Component
public class UpdateServer {
    static String tempPath = System.getProperty("java.io.tmpdir");


    private static Map<Session, BufferedReader> readerMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "name") String name, @PathParam(value = "file") String file){
        String token = session.getRequestParameterMap().get("token").get(0);
        if (token == null) {
            IoUtil.close(session);
            return;
        }
        if(!LoginController.tokens.contains(token)){
            IoUtil.close(session);
            return;
        }
        Map<String, String> pmap = session.getPathParameters();
        System.out.println(pmap);
        //向前端直接输出日志
        ServiceConfig.Config config = findByName(name);
        if (config == null || config.getUpdate() == null || config.getUpdate().isEmpty()) {
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        //查找文件是否存在
        File patch = new File(FileController.path, file);
        if(!FileUtil.exist(patch)){
            return;
        }

        ThreadUtil.execute(() -> {
            Process process = null;
            File tempDir = null;
            try {
                //建议临时文件夹
                tempDir = new File(tempPath, IdUtil.objectId());
                ZipUtil.unzip(patch, tempDir, StandardCharsets.ISO_8859_1);
                //创建真正的更新脚本
                StringBuilder sb = new StringBuilder();
                sb.append("echo 开始更新\n");
                sb.append(String.format("cd %s\n", tempDir.getAbsolutePath()));
                sb.append(config.getUpdate());
                sb.append("\n");
                sb.append("echo 更新完成");
                process = RunScript(sb.toString(), true);
                Process finalProcess = process;
                ThreadUtil.execute(() -> {
                    streamReader(session, finalProcess.getInputStream());
                });
                ThreadUtil.execute(() -> {
                    streamReader(session, finalProcess.getErrorStream());
                });
                CountDownLatch countDownLatch;
                countDownLatchMap.put(session, countDownLatch = new CountDownLatch(1));
                countDownLatch.await();

                send(session, PUSH_LOG, "更新完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (process != null) {
                    try{
                        process.destroy();
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
                FileUtil.del(tempDir);
                FileUtil.del(patch);
                System.out.println("end");
            }
        });
    }


    @OnClose
    public void onClose(Session session){
        CountDownLatch countDownLatch = countDownLatchMap.remove(session);
        if (countDownLatch != null) {
            countDownLatch.countDown();
        }
    }
}
